import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { strings } from '../../../../../../locales/i18n';
import { useRampNavigation } from '../../../../UI/Ramp/hooks/useRampNavigation';
import { RowAlertKey } from '../../components/UI/info-row/alert-row/constants';
import { AlertKeys } from '../../constants/alerts';
import { Alert, Severity } from '../../types/alerts';
import { useTransactionMetadataRequest } from '../transactions/useTransactionMetadataRequest';
import { useConfirmActions } from '../useConfirmActions';
import { useConfirmationContext } from '../../context/confirmation-context';
import { useIsGaslessSupported } from '../gas/useIsGaslessSupported';
import { TransactionType } from '@metamask/transaction-controller';
import { hasTransactionType } from '../../utils/transaction';
import { useTransactionPayToken } from '../pay/useTransactionPayToken';
import { useTransactionPayRequiredTokens } from '../pay/useTransactionPayData';
import { selectUseTransactionSimulations } from '../../../../../selectors/preferencesController';
import { useHasInsufficientBalance } from '../useHasInsufficientBalance';

const IGNORE_TYPES = [TransactionType.predictWithdraw];

export const useInsufficientBalanceAlert = ({
  ignoreGasFeeToken,
}: {
  ignoreGasFeeToken?: boolean;
} = {}): Alert[] => {
  const { goToBuy } = useRampNavigation();
  const transactionMetadata = useTransactionMetadataRequest();
  const { isTransactionValueUpdating } = useConfirmationContext();
  const { onReject } = useConfirmActions();
  const { isSupported: isGaslessSupported, pending: isGaslessCheckPending } =
    useIsGaslessSupported();
  const { payToken } = useTransactionPayToken();
  const requiredTokens = useTransactionPayRequiredTokens();
  const isSimulationEnabled = useSelector(selectUseTransactionSimulations);
  const { hasInsufficientBalance, nativeCurrency } =
    useHasInsufficientBalance();

  const primaryRequiredToken = (requiredTokens ?? []).find(
    (token) => !token.skipIfBalance,
  );

  const isPayTokenTarget =
    payToken &&
    payToken.chainId === primaryRequiredToken?.chainId &&
    payToken.address.toLowerCase() ===
      primaryRequiredToken?.address.toLowerCase();

  return useMemo(() => {
    if (
      !transactionMetadata ||
      isTransactionValueUpdating ||
      (payToken && !isPayTokenTarget)
    ) {
      return [];
    }

    const { selectedGasFeeToken, isGasFeeSponsored, gasFeeTokens } =
      transactionMetadata;

    const isGasFeeTokensEmpty = gasFeeTokens?.length === 0;

    // Check if gasless check has completed (regardless of result)
    const isGaslessCheckComplete = !isGaslessCheckPending;

    // Transaction is sponsored only if it's marked as sponsored AND gasless is supported
    const isSponsoredTransaction = isGasFeeSponsored && isGaslessSupported;

    // Simulation is complete if it's disabled, or if enabled and gasFeeTokens is loaded
    const isSimulationComplete = !isSimulationEnabled || Boolean(gasFeeTokens);

    // Check if user has selected a gas fee token (or we're ignoring that check)
    const hasNoGasFeeTokenSelected = ignoreGasFeeToken || !selectedGasFeeToken;

    // Show alert when gasless check is done and either:
    // - Gasless is NOT supported (user needs native currency for gas)
    // - Gasless IS supported but gasFeeTokens is empty (no alternative tokens available)
    const shouldCheckGaslessConditions =
      isGaslessCheckComplete && (!isGaslessSupported || isGasFeeTokensEmpty);

    const showAlert =
      hasInsufficientBalance &&
      isSimulationComplete &&
      hasNoGasFeeTokenSelected &&
      !hasTransactionType(transactionMetadata, IGNORE_TYPES) &&
      shouldCheckGaslessConditions &&
      !isSponsoredTransaction;

    if (!showAlert) {
      return [];
    }

    return [
      {
        action: {
          label: strings('alert_system.insufficient_balance.buy_action', {
            nativeCurrency,
          }),
          callback: () => {
            goToBuy();
            onReject(undefined, true);
          },
        },
        isBlocking: true,
        field: RowAlertKey.EstimatedFee,
        key: AlertKeys.InsufficientBalance,
        message: strings('alert_system.insufficient_balance.message', {
          nativeCurrency,
        }),
        title: strings('alert_system.insufficient_balance.title'),
        severity: Severity.Danger,
        skipConfirmation: true,
      },
    ];
  }, [
    transactionMetadata,
    isTransactionValueUpdating,
    payToken,
    isPayTokenTarget,
    isGaslessCheckPending,
    isGaslessSupported,
    isSimulationEnabled,
    ignoreGasFeeToken,
    hasInsufficientBalance,
    nativeCurrency,
    goToBuy,
    onReject,
  ]);
};
